/* 
 * Author: apleilx
 * Created on 2015年9月3日, 上午9:59
 */

#ifndef __PROG_GROUP_H
#define	__PROG_GROUP_H

#include "stdint.h"

#ifdef	__cplusplus
extern "C" {
#endif

#define PG_ERR_NONE					0
#define PG_ERR_TAB_FULL				-1
#define PG_ERR_PHY_REUSE			-2
#define PG_ERR_SEG_REUSE			-3
#define PG_ERR_PHY_NOUSE			-4
#define PG_ERR_SEG_NOUSE			-5
#define PG_ERR_GROUP_NOUSE			-6
#define PG_ERR_SUB_FULL				-7

typedef unsigned char pg_gp_site_t;
typedef unsigned char pg_sub_site_t;
typedef unsigned char pg_phy_site_t;

struct pg_element_str
{
	pg_gp_site_t group;
	pg_sub_site_t sub;
	pg_phy_site_t phy;
};

struct pg_man_str
{
	// config
	struct pg_element_str * tab; // 实际tab元素数必须大于tab_size，尾部空白
	pg_phy_site_t tab_size;
	pg_gp_site_t group_max;
	pg_sub_site_t sub_max;
	
	char head_fix;				// fixed head or auto sort
	char cycle;				// cycle or line
	
	// back
	pg_phy_site_t act_num;	// 激活程序数
	int8_t err;
	
	// function 返回结果
	pg_phy_site_t site;		// 在tab中的位置
	pg_gp_site_t group;		// 分组
	pg_sub_site_t sub;		// 子位置
	pg_phy_site_t phy;		// 物理位置
};

/*******************************************************************************
* @brief  config
*******************************************************************************/
int8_t pg_init(struct pg_man_str *, struct pg_element_str * tab, pg_phy_site_t tab_size);
int8_t pg_mode(struct pg_man_str *, char head_fix, char cycle);
int8_t pg_size(struct pg_man_str *, pg_gp_site_t group_max, pg_sub_site_t sub_max);

/*******************************************************************************
* @brief  function
*******************************************************************************/
// 添加段， 返回目标TAB位置 pg.site
int8_t pg_add(struct pg_man_str *, pg_gp_site_t group, pg_sub_site_t sub, pg_phy_site_t phy);
int8_t pg_del_phy(struct pg_man_str *, pg_phy_site_t phy);
int8_t pg_del_seg(struct pg_man_str *, pg_gp_site_t group, pg_sub_site_t sub);

// search
int8_t pg_phy_site(struct pg_man_str *, pg_phy_site_t phy);
int8_t pg_seg_site(struct pg_man_str *, pg_gp_site_t group, pg_sub_site_t sub);
int8_t pg_next_phy(struct pg_man_str *, pg_phy_site_t phy);
int8_t pg_next_seg(struct pg_man_str *, pg_gp_site_t group, pg_sub_site_t sub);
int8_t pg_fore_phy(struct pg_man_str *, pg_phy_site_t phy);
int8_t pg_fore_seg(struct pg_man_str *, pg_gp_site_t group, pg_sub_site_t sub);

// 获取指定分组首个位置。注：定头模式不搜索头区
int8_t pg_group_site(struct pg_man_str *, pg_gp_site_t group);

// 从指定分组获取一个空闲子位置, 结果 man.sub。注：定头模式不搜索头区
int8_t pg_gp_sapce_sub_get(struct pg_man_str *, pg_gp_site_t group);

// 获取指定分组激活数量
pg_phy_site_t pg_seg_amount(struct pg_man_str *);
pg_phy_site_t pg_gp_seg_amount(struct pg_man_str *pg, pg_gp_site_t group);

#ifdef	__cplusplus
}
#endif

#endif	/* __PROG_GROUP_H */

